package com.zzgc.modules.log;

import org.apache.ibatis.javassist.*;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.WebApplicationContext;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 打印接口信息类
 * @Author:
 * @CreateTime: 2023-03-11  11:15
 * @Description:
 * @Version: 1.0
 */
@RestController
//@ApiLog(value = "测试类", url = "/test")
public class WorkLog {
    @Autowired
    WebApplicationContext applicationContext;

    @GetMapping("test")
    //@ApiLog(value = "test方法" , method = RequestMethod.GET, url = "/test")
    public List<String> apiPrint() throws NotFoundException {
        // 获取被ApiLog注解标记的类
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(ApiLog.class);
        List<String> list = new ArrayList<>();
        int number = 1;
        for (Map.Entry<String, Object> entry : beansWithAnnotation.entrySet()) {
            Object value = entry.getValue();
            Class<?> targetClass = AopUtils.getTargetClass(value); // 通过AOP代理获取对象的类
//            Class<?> targetClass = value.getClass(); // 增加了@Transactional会增加AOP代理, 不通过代理获取真实的类，会报错
            ApiLog annotation = targetClass.getAnnotation(ApiLog.class);
            if (annotation != null) {
                list.add("============================================= "
                        + Arrays.toString(annotation.url()) + annotation.value() + ": " + targetClass.getName()
                        + " =============================================");
            }
            // 获取二进制类，得到代码行号
            ClassPool pool = ClassPool.getDefault();
            pool.insertClassPath(new ClassClassPath(targetClass));
            CtClass cc = pool.get(targetClass.getName());

            // 获取对象的方法
            Method[] methods = targetClass.getMethods();
            for (Method declaredField : methods) {
                StringBuffer stringBuffer = new StringBuffer();
                ApiLog annotation1 = declaredField.getAnnotation(ApiLog.class);
                if (annotation1 != null) {
                    CtMethod methodX = cc.getDeclaredMethod(declaredField.getName());
                    int xlineNumber = methodX.getMethodInfo().getLineNumber(0) - 1;
                    String name = targetClass.getName();
                    // 拼接url地址
                    String[] url = annotation1.url();
                    String[] newUrl = null;
                    if (url.length <= annotation.url().length) {
                        newUrl = new String[annotation.url().length];
                    }else {
                        newUrl = new String[url.length];
                    }
                    if (url.length == 0 && annotation.url().length != 0) {
                        newUrl = new String[]{annotation.url()[0]};
                    }else if (annotation.url().length != 0) {
                        for (int i = 0; i < newUrl.length; i++) {
                            String s = "/" + annotation.url()[0] + "/" + url[i];
                            newUrl[i] = s.replaceAll("//","/");
                        }
                    }else {
                        newUrl = url;
                    }
                    stringBuffer.append(number++).append(". ").append("\t")
                            .append(Arrays.toString(annotation1.method())).append(Arrays.toString(newUrl))
                            .append(Arrays.toString(annotation1.params())).append("-").append(annotation1.value()).append(": ")
                            .append(targetClass).append(".").append(declaredField.getName())
                            .append(String.format("(%s.java:%d)", name.substring(name.lastIndexOf(".")+1),xlineNumber));
                    list.add(stringBuffer.toString());
                }
            }
        }
        list.forEach(System.out::println);
        return list;
    }

    //@ApiLog(value = "测试方法", method = RequestMethod.POST)
    public void testa() {
        System.out.println(" = ===== testa() ");
    }

    public static void main(String[] args) {
        System.out.println("添加学生数据 ===> com.comicyu.controller.WorkLog.main(WorkLog.java:18) ");
        System.out.println("WorkLog.main(WorkLog.java:1)");
    }
}
